package com.baiyi.cloud.platform.client.filter;

import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;


/**
 * IP过滤器
 * @param <V>
 * 
 */
@Component
public class IPFilter<V> extends ZuulFilter {
	
	private static final String BIP = "TOOLSBIP" ;
    
	@Autowired
    private RedisTemplate<String,Object> redisTemplate ;
    
	@Value("${system.blacklist.isopen:false}")  
	private Boolean blacklist;  
  

	Logger logger = LoggerFactory.getLogger(getClass());

	@Override
	public Object run() throws ZuulException {
		// 过滤器的具体逻辑。IP校验不通过时我们通过ctx.setSendZuulResponse(false)令zuul过滤该请求，不对其进行路由
        // 然后通过ctx.setResponseStatusCode(401)设置了其返回的错误码，通过ctx.setResponseBody(body)返回body内容
        RequestContext ctx= RequestContext.getCurrentContext();
        HttpServletRequest req=ctx.getRequest();
        String ipAddr=this.getIpAddr(req);
        logger.info("请求IP地址为：[{}]",ipAddr);
        
        //开启黑名单
        if (blacklist) {
        	//配置本地IP黑名单，生产环境可放入数据库或者redis中
            Set<V> ipSet = (Set<V>)redisTemplate.opsForSet().members(BIP);
     
            if (ipSet != null) {
            	if(ipSet.contains(ipAddr)){
                	logger.info("IP地址校验不通过！！！");
                    ctx.setResponseStatusCode(401);
                    ctx.setSendZuulResponse(false);
                    ctx.setResponseBody("IpAddr is forbidden!");
                }
            }
        }
        
        
        logger.info("IP校验通过");
        return null;
	}

	@Override
	public boolean shouldFilter() {
		// 判断该过滤器是否需要被执行。这里我们直接返回true,因此该过滤器对所有请求都会生效,实际运用中我们可以利用该函数来指定过滤器的有效范围
        return true;
	}

	@Override
	public int filterOrder() {
		 // int值来定义过滤器的执行顺序，数值越小优先级越高
        return Integer.MIN_VALUE + 1;
	}

	@Override
	public String filterType() {
		// 过滤器的类型，它决定过滤器在请求的哪个生命周期中执行。这里定义为pre，代表会在请求被路由之前执行。另外还有“route”、“post”、"error”等类型
        return FilterConstants.PRE_TYPE;
	}
	
	
	/**
     * 获取Ip地址
     * @param request
     * @return
     */
    public  String getIpAddr(HttpServletRequest request){
 
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}
